package com.donica.wamstest.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.donica.wamstest.common.Constant;
import com.donica.wamstest.entity.DeviceInfoVO;
import com.donica.wamstest.entity.DeviceVO;
import com.donica.wamstest.entity.FileDTO;
import com.donica.wamstest.entity.TaskStartVO;
import com.donica.wamstest.entity.TaskVO;
import com.donica.wamstest.mapper.DeviceMapper;
import com.donica.wamstest.mapper.TaskMapper;
import com.donica.wamstest.mqtt.MqttPushClient;
import com.donica.wamstest.utils.CommonUtil;

@Service
public class MessageService implements MqttCallbackExtended {
	private static final Logger log = LoggerFactory.getLogger(MessageService.class);

	@Value("${mqtt.server}")
	private String mqttServer;

	@Value("${mqtt.client.id}")
	private String mqttClient;

	@Autowired
	DeviceMapper deviceMapper;
	@Autowired
	TaskMapper taskMapper;

	boolean mqttConnected = false;

	@Override
	public void connectComplete(boolean reconnect, String serverURI) {
		log.info("连接成功," + serverURI);
		mqttConnected = true;
	}

	@Override
	public void connectionLost(Throwable cause) {
		log.info("断开连接," + cause.getMessage());
		mqttConnected = false;
		// 断开连接，建议重连
	}

	@Override
	public void deliveryComplete(IMqttDeliveryToken token) {
		// log.info(token.isComplete() + "");
	}

	public MessageService() {
		// InitMqtt();
	}

	private void InitMqtt() {
		MqttPushClient.MQTT_HOST = mqttServer;
		MqttPushClient.MQTT_CLIENTID = mqttClient + CommonUtil.get32UUID();
		MqttPushClient.MQTT_USERNAME = "username";
		MqttPushClient.MQTT_PASSWORD = "password";
		MqttPushClient client = MqttPushClient.getInstance();
		client.connect(MqttPushClient.MQTT_HOST, MqttPushClient.MQTT_CLIENTID, this);
		client.subscribe(Constant.TOPIC_V1_PROGRAM_DMR2CLOUD);
		client.subscribe(Constant.TOPIC_V1_SOFTWARE_DMR2CLOUD);
		client.subscribe(Constant.TOPIC_V1_CONF_DMR2CLOUD);
		client.subscribe(Constant.TOPIC_V1_CONF_DMR2CLOUD_DATA);
		client.subscribe(Constant.TOPIC_V1_INFO_DMR2CLOUD_DATA);
		client.subscribe(Constant.TOPIC_V1_LOG_DMR2CLOUD);
	}

	@Override
	public void messageArrived(String topic, MqttMessage message) throws Exception {
		log.info("Topic: " + topic);
		log.info("Message: " + new String(message.getPayload()));

		try {
			dealRcvMessage(topic, message);
		} catch (Exception e) {
			// TODO: handle exception
			log.info("dealMessage Exception: " + e.getMessage());
		}
	}
	
	public long InsertDeviceInfo(List<DeviceInfoVO> volist) {
		for (DeviceInfoVO deviceInfoVO : volist) {

			deviceInfoVO.setId(CommonUtil.get32UUID());
			deviceInfoVO.initNullItem();
			deviceInfoVO.calGroupIndex();
		}
		return deviceMapper.InsertDeviceInfo(volist);
	}

	public void dealRcvMessage(String topic, MqttMessage message) throws Exception {
		if (topic.equals(Constant.TOPIC_V1_PROGRAM_DMR2CLOUD) ||
			topic.equals(Constant.TOPIC_V1_SOFTWARE_DMR2CLOUD) || 	
			topic.equals(Constant.TOPIC_V1_CONF_DMR2CLOUD) || 
			topic.equals(Constant.TOPIC_V1_INFO_DMR2CLOUD) || 
			topic.equals(Constant.TOPIC_V1_LOG_DMR2CLOUD)) {
			String s = message.toString();
			TaskVO vo = (TaskVO) JSON.parseObject(s, TaskVO.class);
			//vo.setTask_code("3011");
			List<TaskVO> volist = new ArrayList<>();
			volist.add(vo);
			this.taskMapper.UpdateTask(volist);
			log.info("UpdateTask ok");
		} else if (topic.equals(Constant.TOPIC_V1_INFO_DMR2CLOUD_DATA)) {
			String s = message.toString();
		
			List<DeviceInfoVO> volist = JSON.parseArray(s, DeviceInfoVO.class);;
			this.InsertDeviceInfo(volist);
			log.info("SetDeviceInfo ok");
		} else if (topic.equals(Constant.TOPIC_V1_CONF_DMR2CLOUD_DATA)) {
			String s = message.toString();
			DeviceVO vo = (DeviceVO) JSON.parseObject(s, DeviceVO.class);
			List<DeviceVO> volist = new ArrayList<>();
			volist.add(vo);
			this.deviceMapper.UpdateDevice(volist);
			log.info("UpdateDevice ok");
		}
	}

	public void queryDeviceInfo() {
		TaskVO vo = new TaskVO();
		vo.setId(CommonUtil.get32UUID());
		vo.setObject_code("");
		vo.setTask_code(Constant.TASK_CODE_DMRINFO_GET);

		String paylodString = JSON.toJSONString(vo);
		MqttPushClient.getInstance().publish(Constant.TOPIC_V1_INFO_CLOUD2DMR, paylodString,false);
	}

	public long startTask(TaskStartVO vo) throws Exception {
		if (vo.getObject_codes() == null) {
			throw new Exception("object_codes can't be null");
		}

		if (vo.getTask_code() == null) {
			throw new Exception("task_code can't be null");
		}
		
		if (vo.getTask_code() == Constant.TASK_CODE_PROGRAM_DOWNLOAD ||
			vo.getTask_code() == Constant.TASK_CODE_SOFTWARE_DOWNLOAD	) {
			
			if(vo.getData() == null) {
				throw new Exception("download task data can't be null");
			}
			
		}

		List<TaskVO> volist = new ArrayList<>();
		List<TaskVO> subTasklist = new ArrayList<>();
		for (String codeTmp : vo.getObject_codes()) {
			TaskVO voTmp = new TaskVO();
			voTmp.setId(CommonUtil.get32UUID());
			voTmp.setObject_code(codeTmp);
			voTmp.setTask_code(vo.getTask_code());
			voTmp.setTask_level("1");
			voTmp.setUri(vo.getUri());
			voTmp.setCreator(vo.getCreator());
			voTmp.setFrag_size(vo.getFrag_size());
			voTmp.setThread(vo.getThread());
			voTmp.setData(vo.getData());
			voTmp.setStatus("0");

			
			if(vo.getData() != null) {
				long totalSize = 0L;
				
				List<FileDTO> filelistDtos = vo.getData().getFilelist();

				if (filelistDtos != null) {
					for (FileDTO file : filelistDtos) {

						totalSize += file.getSize();
						TaskVO voTmpSub = new TaskVO();
						voTmpSub.setId(voTmp.getId());
						voTmpSub.setObject_code(codeTmp);
						voTmpSub.setTask_code(Constant.TASK_CODE_PROGRAM_DOWNLOAD_SUB);
						voTmpSub.setTask_level("2");
						voTmpSub.setUri(file.getUri());
						voTmpSub.setCreator(vo.getCreator());
						voTmpSub.setFrag_size(vo.getFrag_size());
						voTmpSub.setThread(vo.getThread());
						voTmpSub.setTotal_size(file.getSize());
						subTasklist.add(voTmpSub);
					}
					voTmp.setTotal_size(totalSize);
				} else {
					
				}
			}
			
			volist.add(voTmp);

			String paylodString = JSON.toJSONString(voTmp);
			MqttPushClient.getInstance().publish(Constant.TOPIC_V1_PROGRAM_CLOUD2DMR + codeTmp, paylodString,true);
		}

		volist.addAll(subTasklist);
		for (TaskVO taskVO : volist) {
			taskVO.initNullItem();
		}

		return this.taskMapper.InsertTask(volist);
	}

	public boolean isMqttConnected() {
		return this.mqttConnected;
	}

	@Scheduled(initialDelay = 1000L, fixedDelay = 600000000L)
	public void reportCurrentTime() {
		System.out.println("现在时间：" + new Date());
		if (!this.mqttConnected)
			InitMqtt();
	}

	@Scheduled(initialDelay = 5000L, fixedDelay = 60000L)
	public void queryDeviceInfoTimer() {
		System.out.println("queryDeviceInfo 现在时间：" + new Date());
		System.out.println("mqttConnected ：" + mqttConnected);
		queryDeviceInfo();
	}
}
